package br.mikhas.lab.scanner;

/**
 * The lexer
 * 
 * @author Mikhail Domanoski
 * 
 */
public class Lexer {
	/**
	 * The machine's initial state
	 */
	private final State initialState;

	/**
	 * Creates a new state machine and defines the initial state
	 * 
	 * @param initial
	 */
	public Lexer(State initial) {
		this.initialState = initial;
	}

	/**
	 * Gets the next token in the char stream
	 * 
	 * @param stream
	 *            A char stream which stores the state of the read chars during
	 *            the process
	 * @return The next token in the stream
	 */
	public Token nextToken(CharStream stream) {
		int initialPosition = stream.currentPosition();
		State state = initialState;
		State lastFinalState = null;
		int lastFinalPosition = initialPosition;

		while (stream.hasNext()
				&& (state = state.nextState(stream.nextChar())) != null) {
			if (state.isFinalState()) {
				lastFinalState = state;
				lastFinalPosition = stream.currentPosition();
			}
		}

		stream.setPosition(lastFinalPosition);

		if (lastFinalState != null) {
			return new Token(lastFinalState.getTokenType(), stream,
					initialPosition, lastFinalPosition);
		} else {
			return null;
		}
	}
}
